package com.xingda.packing.minitor.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xingda.packing.annotation.LimitRequest;
import com.xingda.packing.appset.AppSetService;
import com.xingda.packing.common.BaseController;
import com.xingda.packing.common.OperationConstant;
import com.xingda.packing.common.PackUtils;
import com.xingda.packing.common.R;
import com.xingda.packing.common.dto.PageDto;
import com.xingda.packing.domain.PackDemandRange;
import com.xingda.packing.domain.ProductArea;
import com.xingda.packing.enums.BoxTaskType;
import com.xingda.packing.http.PackingRequireHttp;
import com.xingda.packing.annotation.OpLog;
import com.xingda.packing.minitor.dto.*;
import com.xingda.packing.minitor.entity.*;
import com.xingda.packing.minitor.mapper.PkBoxLocationRealtionMapper;
import com.xingda.packing.minitor.mapper.PkCacheLocationMapper;
import com.xingda.packing.minitor.mapper.PkTaskMapper;
import com.xingda.packing.minitor.mapper.PkWheelMapper;
import com.xingda.packing.minitor.service.IPkBoxLocationService;
import com.xingda.packing.minitor.service.IPkTaskService;
import com.xingda.packing.plc.service.PlcDirectiveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author anxiaoning
 * @since 2021-07-03
 */
@RestController
@RequestMapping("/api/task")
@Slf4j
public class PkTaskController extends BaseController {
    private final static String PACK_HEAD = "PACK";
    @Resource
    private IPkTaskService pkTaskService;
    @Resource
    private IPkBoxLocationService pkBoxLocationService;
    @Resource
    PlcDirectiveService plcDirectiveService;
    @Resource
    private AppSetService appSetService;
    @Resource
    private ProductArea productArea;
    @Value("${spring.profiles.active}")
    private String env;
    @Resource
    private PkBoxLocationRealtionMapper pkBoxLocationRealtionMapper;
    @Resource
    private PkTaskMapper pkTaskMapper;
    @Resource
    private PkCacheLocationMapper pkCacheLocationMapper;
    @Resource
    private PkWheelMapper pkWheelMapper;

    @GetMapping("/getPage")
    public R getPkTaskPage(PageDto dto) {
        Page<PkTaskDto> page = this.pkTaskService.getPkTaskPage(dto);
        return R.ok().put("data", page);
    }


    @GetMapping("/getDetail")
    public R getDetail(@RequestParam Integer taskId) {
        PkTaskDetailDto pkTaskDetailDto = pkTaskService.getPkTaskDetailById(taskId);
        return R.ok().put("data", pkTaskDetailDto);
    }

    @PostMapping("/getList")
    public R getPkTaskList(@RequestBody PkTaskDto dto) {

        return R.ok().put("data", this.pkTaskService.getPkTaskList(dto.getId()));
    }

    @GetMapping("/getWheelTag")
    public R getWheelTag(String code, Integer area) {
        if (code.startsWith(PACK_HEAD)) {
            code = code.substring(code.indexOf(PACK_HEAD) + PACK_HEAD.length());
        }
        PkBoxDetailInfoDto dto = this.pkTaskService.getScanCodeInfo(code);
        Set<String> newStrings = new HashSet<>();
        for (String string : productArea.getProductMap(area).keySet()) {
            if (string.split("-")[1].equals(dto.getBoxInfo().getWheelTypeName())) {
                newStrings.add(string);
            }
        }
        return R.ok().put("data", newStrings);
    }

    public String getWheelTag2(String code, Integer area) {
        if (code.startsWith(PACK_HEAD)) {
            code = code.substring(code.indexOf(PACK_HEAD) + PACK_HEAD.length());
        }
        PkBoxDetailInfoDto dto = this.pkTaskService.getScanCodeInfo(code);
        Set<String> newStrings = new HashSet<>();
        for (String string : productArea.getProductMap(area).keySet()) {
            if (string.split("-")[1].equals(dto.getBoxInfo().getWheelTypeName())) {
                newStrings.add(string);
            }
        }
        return newStrings.toString();
    }

    @GetMapping("/scanCode")
    public R scanCode(String code, Integer area) {

        try {
            if (Objects.isNull(code) || "".equals(code.trim())) {
                return R.error("无条码参数-code");
            }

            if (code.startsWith(PACK_HEAD)) {
                code = code.substring(code.indexOf(PACK_HEAD) + PACK_HEAD.length());
            }

            PkBoxDetailInfoDto dto = this.pkTaskService.getScanCodeInfo(code);
            if (dto == null) {
                return R.error("找不到对应的装箱信息:" + code);
            }
            if (code.startsWith("A")) {
                PkTask pkTask = appSetService.getTaskByCode(code);
                HashMap<String, Integer> productMap = productArea.getProductMap(area);
                if (pkTask.getType() == 5) {
                    if (productMap.isEmpty()) {
                        return R.error("当前区域未设置成品装箱区,请设置完成品再设置半成品装箱");
                    }
                    List<String> collect = productMap.keySet().stream().map(m -> m.split("-")[1]).collect(Collectors.toList());
                    if (!collect.contains(dto.getBoxInfo().getWheelTypeName())) {
                        return R.error("当前半成品条码不满足已有的装箱规格");
                    }
                }
                if (pkTask.getType() == 2) {
                    if (productMap.isEmpty()) {
                        return R.error("当前区域未设置成品装箱区,请设置完成品再设置清线装箱");
                    }
                }
            }
            return R.ok().put("data", dto);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.error();
    }

    @LimitRequest(count = 1)
    @PostMapping("removeWheel")
    @OpLog(username = "#removeInputDto.username", corp = "#removeInputDto.corp", veri = "#removeInputDto.veri", opItem = OperationConstant.REMOVE_WHEEL, param = "#removeInputDto.barCode")
    public R removeWheel(@RequestBody RemoveInputDto removeInputDto) {
        if (Objects.isNull(removeInputDto.getBarCode())) {
            return R.error("轮号参数错误");
        }
        if (Objects.isNull(removeInputDto.getTaskId())) {
            return R.error("任务id参数错误");
        }
        if (Objects.isNull(removeInputDto.getWheelId())) {
            return R.error("工字轮id参数错误");
        }
        try {
            boolean result = pkTaskService.removeWheel(removeInputDto);
            if (result) {
                return R.ok();
            }
            return R.error("操作失败");
        } catch (Exception e) {
            log.info(e.getMessage());
            e.printStackTrace();
        }
        return R.error("操作失败");
    }

    @LimitRequest(count = 1)
    @PostMapping("/save")
    @OpLog(username = "#pkBoxInfoSetInput.username", corp = "#pkBoxInfoSetInput.corp", veri = "#pkBoxInfoSetInput.veri", opItem = OperationConstant.SAVE_TASK, param = "#pkBoxInfoSetInput.boxLocationId")
    public R save(@RequestBody PkBoxInfoSetInput pkBoxInfoSetInput) {
        if (Objects.isNull(pkBoxInfoSetInput)) {
            return R.error("无参数");
        }
        if (Objects.isNull(pkBoxInfoSetInput.getCode()) || "".equals(pkBoxInfoSetInput.getCode().trim())) {
            return R.error("无条码参数-code");
        }
        Integer boxLocationId = pkBoxInfoSetInput.getBoxLocationId();
        LambdaQueryWrapper<PkBoxLocationRealtion> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PkBoxLocationRealtion::getBoxLocationId, boxLocationId);
        PkBoxLocationRealtion pkBoxLocationRealtion = pkBoxLocationRealtionMapper.selectOne(lambdaQueryWrapper);
        if (Objects.nonNull(pkBoxLocationRealtion)) {
            PkTask pt = pkTaskMapper.selectById(pkBoxLocationRealtion.getTaskId());
            if (pt.getState() == 2) {
                return R.error("当前装箱区未完成装箱任务,如需保存新的任务,请执行重置操作");
            }
        }
        int area;
        if (boxLocationId > 10) {
            area = 2;
        } else {
            area = 1;
        }
        String code = pkBoxInfoSetInput.getCode();
        if (code.startsWith(PACK_HEAD)) {
            code = code.substring(code.indexOf(PACK_HEAD) + PACK_HEAD.length());
            pkBoxInfoSetInput.setCode(code);
        }
        // 自定义任务(清线任务、不合格产品任务、半成品任务、不可用任务)
        PkTask pkTask = appSetService.getTaskByCode(code);
        // 中筒允许装的物料
        List<PkBom> pkBoms = null;
        // 从已经开始的装箱中装箱工字轮信息
        JSONArray packinglists = null;
        if (Objects.isNull(pkTask)) {
            JSONObject packingInfoJson = PackingRequireHttp.searchPackingBoxInspection(pkBoxInfoSetInput.getCode(), false, false, false, true);
            pkTask = PackUtils.toPkTask(packingInfoJson);
            pkTask.setCustomer(pkBoxInfoSetInput.isCustomer());
            pkTask.setType(BoxTaskType.PACKING_FINISHED.getTypeId());
            // 中筒允许装的物料
            pkBoms = PackUtils.toPkBoms(packingInfoJson);
            PkBom pkBom = pkBoms.get(0);
            String tag = pkBom.getInvname() + "-" + pkTask.getWheelTypeName() + "-" + pkTask.getFixedLength();
            HashMap<String, Integer> productMap = productArea.getProductMap(area);
//            if (productMap.size() == 3 && !productMap.containsKey(tag)) {
//                return R.error("已超过设定的装箱规格:3,设置失败!!!");
//            }
//            //判断成品装箱是否少于4个
//            if (!productArea.canSaveTask(area, tag, boxLocationId)) {
//                return R.error("已超过规定的成品装箱数量:6,设置失败!!");
//            }
            pkTask.setWheelTagMap(tag);
            pkTask.setWheelTag(tag + "-" + PackUtils.getColorByWheelTypeNameAndSurfaceLr(pkTask.getWheelTypeName(), pkTask.getSurfaceLr()));
            // 装箱工字轮信息
            packinglists = packingInfoJson.getJSONArray("packinglists");
        }
        if (pkTask.getType() == 5) {
            pkTask.setWheelTag("NOT-" + pkBoxInfoSetInput.getWheelTag());
            pkTask.setWheelTagMap(pkBoxInfoSetInput.getWheelTag());
        }
        if (pkTask.getType() == 2) {
            pkTask.setWheelTag(pkBoxInfoSetInput.getWheelTag());
            pkTask.setWheelTagMap(pkBoxInfoSetInput.getWheelTag());
            //从缓存位查询是否有当前清线规格的工字轮
            LambdaQueryWrapper<PkCacheLocation> pkCacheLocationLambdaQueryWrapper = new LambdaQueryWrapper<>();
            pkCacheLocationLambdaQueryWrapper.isNotNull(PkCacheLocation::getWheelId);
            pkCacheLocationLambdaQueryWrapper.eq(PkCacheLocation::getArea, area);
            List<PkCacheLocation> pkCacheLocations = pkCacheLocationMapper.selectList(pkCacheLocationLambdaQueryWrapper);
            if (pkCacheLocations.isEmpty()) {
                return R.error("当前缓存位没有工字轮");
            }
            List<Integer> collect = pkCacheLocations.stream().map(PkCacheLocation::getWheelId).collect(Collectors.toList());
            List<String> strings = pkWheelMapper.selectBatchIds(collect).stream().map(PkWheel::getWheelTagMap).collect(Collectors.toList());
            if (!strings.contains(pkBoxInfoSetInput.getWheelTag())) {
                return R.error("当前缓存位不存在可以清线的工字轮");
            }
        }
        if (pkTask.getType() != 1) {
            if (Objects.isNull(pkBoxInfoSetInput.getWheelTag())) {
                return R.error("未选择装箱类型");
            }
        }
        if (Objects.isNull(pkBoxInfoSetInput.getPalletType())) {
            return R.error("托盘类型未选择");
        }
        PackDemandRange wheelTorsion = pkBoxInfoSetInput.getWheelTorsion();
        if (validateRange(wheelTorsion) || (wheelTorsion.getMax().compareTo(wheelTorsion.getMin()) == 0)) {
            return R.error("轮扭转值参数错误！-wheelTorsion");
        }
        PackDemandRange floorTorsion = pkBoxInfoSetInput.getFloorTorsion();
        if (validateRange(floorTorsion) || (floorTorsion.getMax().compareTo(floorTorsion.getMin()) == 0)) {
            return R.error("层扭转和参数错误！-floorTorsion");
        }
        PackDemandRange boxSolderNum = pkBoxInfoSetInput.getBoxSolderNum();
        if (boxSolderNum.isEnable() && Objects.isNull(boxSolderNum.getMax())) {
            return R.error("箱焊点数参数错误！-boxSolderNum");
        }
        PackDemandRange boxDeviation = pkBoxInfoSetInput.getBoxDeviation();
        if (boxDeviation.isEnable() && Objects.isNull(boxDeviation.getMax())) {
            return R.error("箱标准差参数错误！-boxDeviation");
        }
        PackDemandRange floorSameMachineNum = pkBoxInfoSetInput.getFloorSameMachineNum();
        if (floorSameMachineNum.isEnable() && (Objects.isNull(floorSameMachineNum.getMax()))) {
            return R.error("层同床轮数参数错误！-floorSameMachineNum");
        }
        PackDemandRange floor1SolderWheelNum = pkBoxInfoSetInput.getFloorSolderWheelNum().getFloor1SolderWheelNum();
        if (Objects.nonNull(floor1SolderWheelNum) && floor1SolderWheelNum.isEnable() && (Objects.isNull(floor1SolderWheelNum.getMin()) || Objects.isNull(floor1SolderWheelNum.getMax()) || floor1SolderWheelNum.getMax().compareTo(floor1SolderWheelNum.getMin()) < 0)) {
            return R.error("一层重卷轮参数错误！-floor1SolderWheelNum");
        }
        PackDemandRange floor2SolderWheelNum = pkBoxInfoSetInput.getFloorSolderWheelNum().getFloor2SolderWheelNum();
        if (validateRange(floor2SolderWheelNum)) {
            return R.error("二层重卷轮参数错误！-floor1SolderWheelNum");
        }
        PackDemandRange floor3SolderWheelNum = pkBoxInfoSetInput.getFloorSolderWheelNum().getFloor3SolderWheelNum();
        if (validateRange(floor3SolderWheelNum)) {
            return R.error("三层重卷轮参数错误！-floor1SolderWheelNum");
        }
        PackDemandRange floor1SolderNum = pkBoxInfoSetInput.getFloorSolderNum().getFloor1SolderNum();
        if (Objects.nonNull(floor1SolderNum) && floor1SolderNum.isEnable() && (Objects.isNull(floor1SolderNum.getMin()) || Objects.isNull(floor1SolderNum.getMax()) || floor1SolderNum.getMax().compareTo(floor1SolderNum.getMin()) < 0)) {
            return R.error("一层焊点参数错误！-floor1SolderWheelNum");
        }
        PackDemandRange floor2SolderNum = pkBoxInfoSetInput.getFloorSolderNum().getFloor2SolderNum();
        if (Objects.nonNull(floor2SolderNum) && floor2SolderNum.isEnable() && (Objects.isNull(floor2SolderNum.getMin()) || Objects.isNull(floor2SolderNum.getMax()) || floor2SolderNum.getMax().compareTo(floor2SolderNum.getMin()) < 0)) {
            return R.error("二层焊点参数错误！-floor1SolderWheelNum");
        }
        PackDemandRange floor3SolderNum = pkBoxInfoSetInput.getFloorSolderNum().getFloor3SolderNum();
        if (Objects.nonNull(floor3SolderNum) && floor3SolderNum.isEnable() && (Objects.isNull(floor3SolderNum.getMin()) || Objects.isNull(floor3SolderNum.getMax()) || floor3SolderNum.getMax().compareTo(floor3SolderNum.getMin()) < 0)) {
            return R.error("三层焊点参数错误！-floor1SolderWheelNum");
        }
        if (pkTask.getWheelTypeName().equals("B60") || pkTask.getWheelTypeName().equals("B40") || pkTask.getWheelTypeName().equals("B40/B60")) {
            PackDemandRange floor4SolderWheelNum = pkBoxInfoSetInput.getFloorSolderWheelNum().getFloor4SolderWheelNum();
            if (validateRange(floor4SolderWheelNum)) {
                return R.error("四层重卷轮参数错误！-floor1SolderWheelNum");
            }
            PackDemandRange floor5SolderWheelNum = pkBoxInfoSetInput.getFloorSolderWheelNum().getFloor5SolderWheelNum();
            if (validateRange(floor5SolderWheelNum)) {
                return R.error("五层重卷轮参数错误！-floor1SolderWheelNum");
            }
            PackDemandRange floor6SolderWheelNum = pkBoxInfoSetInput.getFloorSolderWheelNum().getFloor6SolderWheelNum();
            if (validateRange(floor6SolderWheelNum)) {
                return R.error("六层重卷轮参数错误！-floor1SolderWheelNum");
            }
            PackDemandRange floor4olderNum = pkBoxInfoSetInput.getFloorSolderNum().getFloor4SolderNum();
            if (Objects.nonNull(floor4olderNum) && floor4olderNum.isEnable() && (Objects.isNull(floor4olderNum.getMin()) || Objects.isNull(floor4olderNum.getMax()) || floor4olderNum.getMax().compareTo(floor4olderNum.getMin()) < 0)) {
                return R.error("四层焊点参数错误！-floor1SolderWheelNum");
            }
            PackDemandRange floor5SolderNum = pkBoxInfoSetInput.getFloorSolderNum().getFloor5SolderNum();
            if (Objects.nonNull(floor5SolderNum) && floor5SolderNum.isEnable() && (Objects.isNull(floor5SolderNum.getMin()) || Objects.isNull(floor5SolderNum.getMax()) || floor5SolderNum.getMax().compareTo(floor5SolderNum.getMin()) < 0)) {
                return R.error("五层焊点参数错误！-floor1SolderWheelNum");
            }
            PackDemandRange floor6SolderNum = pkBoxInfoSetInput.getFloorSolderNum().getFloor6SolderNum();
            if (Objects.nonNull(floor6SolderNum) && floor6SolderNum.isEnable() && (Objects.isNull(floor6SolderNum.getMin()) || Objects.isNull(floor6SolderNum.getMax()) || floor6SolderNum.getMax().compareTo(floor6SolderNum.getMin()) < 0)) {
                return R.error("六层焊点参数错误！-floor1SolderWheelNum");
            }
        }
        PkBoxLocation pkBoxLocation = pkBoxLocationService.getById(boxLocationId);
        if (Objects.isNull(pkBoxLocation)) {
            return R.error("装箱位查不到对象-boxLocationId");
        }
        if (env.startsWith("xd-prod")) {
            if (!plcDirectiveService.isTrue(pkBoxLocation.getPalletComing())) {
                return R.error("装箱位托盘未移入-boxLocationId");
            }
        }
        try {
            boolean result = this.pkTaskService.save(pkBoxInfoSetInput, pkTask, pkBoms, packinglists, boxLocationId, area);
            if (result) {
                return R.ok();
            }
        } catch (Exception e) {
            log.info(e.getMessage());
            e.printStackTrace();
        }
        return R.error();
    }

    /**
     * 验证通过,返回true; 否则返回false
     */
    private boolean validateRange(PackDemandRange packDemandRange) {
        if (Objects.nonNull(packDemandRange)) {
            return packDemandRange.isEnable() && (Objects.isNull(packDemandRange.getMin()) || Objects.isNull(packDemandRange.getMax()) || packDemandRange.getMax().compareTo(packDemandRange.getMin()) < 0);
        }
        return false;
    }
}
